#include <unistd.h>
#include <getopt.h>

#include "Enesim.h"
#include "Emage.h"
#include "Ender.h"
#include "Escen.h"

typedef struct _Escen2Img
{
	char *file;
	Enesim_Surface *surface;
	Escen *escen;
	Escen_Ender *ender;
	Escen_State *state;
	Escen_Instance *instance;
} Escen2Img;


typedef struct _Escen2Img_Parse
{
	char *file;
	char *name;
	char *image;
	char *state;
	char *ender;
} Escen2Img_Parse;

/**
 * We bascially should load the escen
 * load the escen ender, set the state and dump
 * every frame into a file
 */
static Eina_Bool _instance_timer_cb(void *data)
{
	Escen2Img *e2i = data;
	Ender_Element *ender;
	Enesim_Renderer *r;
	static int count = 0;
	char outfile[PATH_MAX];

	snprintf(outfile, PATH_MAX, "%s%08d.png", e2i->file, count);
	/* dump the current frame into an image */
	ender = escen_instance_ender_get(e2i->instance);
	r = ender_element_renderer_get(ender);
	enesim_renderer_draw(r, e2i->surface, NULL, 0, 0, NULL);
	escen_instance_process(e2i->instance);
	printf("Saving %s\n", outfile);
	enesim_image_file_save(outfile, e2i->surface, NULL);
	if (escen_instance_current_state_finalized(e2i->instance))
	{
		ecore_main_loop_quit();
	}
	count++;

        return EINA_TRUE;
}

static void help(void)
{
	printf("Usage: escen2img OPTIONS\n");
	printf("Where OPTIONS can be one of the following\n");
	printf("-h, --help This help message\n");
	printf("-f, --file The .escen file to load\n");
	printf("-o, --odir The output directory to write the images\n");
	printf("-e, --ender The escen ender name\n");
	printf("-s, --state The escen ender state\n");
	printf("-i, --image The image name \n");
}

static Eina_Bool parse(Escen2Img_Parse *e2ip, int argc, char **argv)
{
	Eina_Bool ret = EINA_TRUE;
	char *short_options = "ho:e:f:s:i:";
	struct option long_options[] = {
		{"help", 0, 0, 'h'},
		{"odir", 1, 0, 'o'},
		{"file", 1, 0, 'f'},
		{"ender", 1, 0, 'e'},
		{"state", 1, 0, 's'},
		{"image", 1, 0, 'i'},
		{0, 0, 0, 0}
	};
	int c;
	int option;

	/* handle the parameters */
	while ((c = getopt_long(argc, argv, short_options, long_options,
			&option)) != -1)
	{
		switch (c)
		{
			case 'h':
			help();
			return 0;

			case 'e':
			e2ip->ender = strdup(optarg);
			break;

			case 's':
			e2ip->state = strdup(optarg);
			break;

			case 'i':
			e2ip->image = strdup(optarg);
			break;

			case 'f':
			e2ip->file = strdup(optarg);
			break;

			default:
			break;
		}
	}
	/* mandatory */
	if (!e2ip->file)
		ret = EINA_FALSE;
	if (!e2ip->image)
		e2ip->image = strdup("image");
	if (!e2ip->ender)
		ret = EINA_FALSE;
	if (!e2ip->state)
	{
		e2ip->state = strdup("default");
	}

	return ret;
}


int main(int argc, char **argv)
{
	Escen2Img e2i;
	Escen2Img_Parse e2ip;
	double spf;

	memset(&e2ip, 0, sizeof(Escen2Img_Parse));
	if (!parse(&e2ip, argc, argv))
	{
		help();
		return 0;
	}

	escen_init();
	enesim_image_init();
	ecore_init();

	/* get the output file */
	/* TODO use the out dir too */
	e2i.file = strdup(e2ip.image);
	/* get the escen */
	e2i.escen = escen_parser_load(e2ip.file);
	if (!e2i.escen)
	{
		printf("Impossible to parse the file %s\n", e2ip.file);
		return 1;
	}
	/* get the ender */
	e2i.ender = escen_ender_get(e2i.escen, e2ip.ender);
	if (!e2i.ender)
	{
		printf("No escen ender available\n");
		return 1;
	}
	/* get the state to display */
	e2i.state = escen_ender_state_get(e2i.ender, e2ip.state);
	if (!e2i.state)
	{
		printf("No escen state available\n");
		return 1;
	}
	/* TODO if not set, just use the default one */
	/* TODO parse the size of the destination image (can we get it from the instance itself?) */
	/* create the surface */
	e2i.surface = enesim_surface_new(ENESIM_BACKEND_SOFTWARE, ENESIM_FORMAT_ARGB8888, 256, 256);
	/* create the instance */
	e2i.instance = escen_instance_new(e2i.ender);
	/* set the state */
	escen_instance_state_set(e2i.instance, e2i.state);
	/* parse the limit on time, useful whenever we support loops on animations */
	/* add the timer */
	/* start processing the instance until the state is finished */
	spf = 1.0/escen_fps_get(e2i.escen);
	ecore_timer_add(spf, _instance_timer_cb, &e2i);

	ecore_main_loop_begin();

	ecore_shutdown();
	escen_shutdown();
	enesim_image_shutdown();

	return 0;
}
